package cn.wolfcode.luowowo.member.service.impl;

import cn.wolfcode.luowowo.cache.prefix.UserInfoKeyPrefix;
import cn.wolfcode.luowowo.cache.prefix.VerifyCodeKeyPrefix;
import cn.wolfcode.luowowo.cache.service.IRedisService;
import cn.wolfcode.luowowo.cache.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.cache.service.IVerifyCodeRedisService;
import cn.wolfcode.luowowo.common.exception.LogicException;
import cn.wolfcode.luowowo.common.util.AssertUtil;
import cn.wolfcode.luowowo.member.domain.UserInfo;
import cn.wolfcode.luowowo.member.mapper.UserInfoMapper;
import cn.wolfcode.luowowo.member.service.IUserInfoService;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StreamUtils;

import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service //注意包
public class UserInfoServiceImpl implements IUserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Reference
    private IVerifyCodeRedisService verifyCodeRedisService;
    @Reference
    private IUserInfoRedisService userInfoRedisService;
    @Reference
    private IRedisService redisService;

    @Override
    public List<UserInfo> list() {
        return userInfoMapper.selectAll();
    }


    @Override
    public String update(UserInfo userInfo) {
        userInfoMapper.update(userInfo);
        UserInfo user = userInfoMapper.selectByPrimaryKey(userInfo.getId());
        return createToken(user);
    }

    /**
     * 文件上传加路径修改
     * @param
     * @param
     * @return
     * @throws LogicException
     */
    @Override
    public String updateheadImg(String path, Long id) {

        userInfoMapper.updateheadImg("/"+path,id);
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(id);
        return createToken(userInfo);
    }

    //查询所有关注的人
    @Override
    public List<UserInfo> getFromId(Long id) {
        List<UserInfo> userInfos = userInfoMapper.getFromId(id);
        return userInfos;
    }
    //查询所有的粉丝
    @Override
    public List<UserInfo> getFans(Long id) {
        List<UserInfo> userInfos = userInfoMapper.getFansById(id);
        return userInfos;
    }

    @Override
    public String updatePassWord(String newpassword, Long id) {
        userInfoMapper.updatePassWord(newpassword,id);
        UserInfo user = userInfoMapper.selectByPrimaryKey(id);
        return createToken(user);
    }

    //登录
    @Override
    public String userLogin(String username, String password) throws LogicException {
        //判断账号和密码
        AssertUtil.hasLength(username);
        AssertUtil.hasLength(password);
        UserInfo userInfo = userInfoMapper.selectByPhoneAndPassword(username, password);
        if(userInfo == null){
            throw new LogicException("用户名或密码错误");
        }
        //保存缓存信息
        return createToken(userInfo);
    }

    //创建token
    private String createToken(UserInfo userInfo)  throws LogicException {
        String token = UUID.randomUUID().toString().replace("-", "");
        //添加到redis中
        userInfoRedisService.addToken(UserInfoKeyPrefix.USER_INFO_TOKEN, token, userInfo);
        return token;
    }

    //根据账号密码查询数据库获取UserInfo
    @Override
    public UserInfo get(Long id)  throws LogicException {
        return userInfoMapper.selectByPrimaryKey(id);
    }

    //判断注册手机号
    @Override
    public boolean checkPhone(String phone)  throws LogicException {
        //查询用户是否注册
        return userInfoMapper.selectUserByPhone(phone) > 0;
    }

    //注册操作
    @Override
    public void regist(String phone, String nickname, String password, String rpassword, String verifyCode) throws LogicException{
        //断言参数是否为空或空字符串
        AssertUtil.hasLength(nickname);
        AssertUtil.hasLength(password);
        AssertUtil.hasLength(rpassword);
        AssertUtil.hasLength(verifyCode);
        AssertUtil.hasLength(phone);
        //判断账户是否注册
        if(this.checkPhone(phone)){
            throw new LogicException("该手机号已经注册");
        }
        //验证两次密码一致
        AssertUtil.isEquals(password, rpassword, "两次输入密码不一致");
        //判断验证码是否正确
        String redisCode = verifyCodeRedisService.getVerifyCode(VerifyCodeKeyPrefix.VERIFY_CODE, phone); //获取redis中的验证码
        if(!redisCode.equalsIgnoreCase(verifyCode)){
            throw new LogicException("验证码错误");
        }
        //注册操作
        UserInfo userInfo = new UserInfo();
        userInfo.setPassword(password); //密码必须加密, 这里假设已经加密

        userInfo.setNickname(nickname);
        userInfo.setPhone(phone);
        userInfo.setGender(UserInfo.GENDER_SECRET);
        userInfo.setState(UserInfo.STATE_NORMAL);
        userInfo.setHeadImgUrl("/images/default.jpg");
        userInfo.setLevel(1);
        userInfoMapper.insert(userInfo);
    }

    //发送短信验证码与缓存
    @Override
    public void sendVerifyCode(String phone) throws LogicException {
        //1.生成短信验证码
        String code = UUID.randomUUID().toString().substring(0, 4);
        System.out.println(code);

        //2.发送到用户手机
        //System.out.println(code); //模拟发送短信
        if(!redisService.exists(VerifyCodeKeyPrefix.VERIFY_CODE, phone)){
            try {
                this.sendMsg(phone, code);
            } catch (Exception e) {
                throw new LogicException("短信发送失败");
            }
        }else{
            throw new LogicException("短信已经发送, 请勿重复操作");
        }

        //3.缓存 verify:15900000000 code
        if(!this.checkPhone(phone)){
            verifyCodeRedisService.setVerifyCode(phone, code);
        }
    }

    @Value("${msg.url}")
    private String msgUrl;
    @Value("${msg.appkey}")
    private String appkey;

    //发送短信验证码到用户手机端
    public void sendMsg(String phone, String code) throws Exception {

        //方式1：HttpClient 这个开源框架， 完全可以模拟出浏览器所有操作
        //方式2：jdk自带的
        //指定访问地址
        URL url = new URL(msgUrl);
        //建立连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        //设置请求方法
        connection.setRequestMethod("GET");
        //设置请求参数 //..?tos=13580305095&msg=【中正云通信】您的验证码是8888 退订回T&appkey=您申请的APPKEY
        StringBuilder sb = new StringBuilder(100);
        sb.append("tos=").append(phone)
                .append("&msg=").append("【中正云通信】您的验证码是").append(code)
                .append(" 退订回T").append("&appkey=").append(appkey);
        //默认是false， 设置true表示输出参数
        connection.setDoOutput(true);
        connection.getOutputStream().write(sb.toString().getBytes("UTF-8"));
        //请求连接
        connection.connect();
        //获取响应数据
            //{"code":"10000","charge":false,"remain":0,"msg":"查询成功","result":{"Status":"Success","MsgID":"0706220451215012","MsgInfo":"提交成功","ExRecords":"1","ExMoney":"0.05"}}
        String resp = StreamUtils.copyToString(connection.getInputStream(), Charset.forName("UTF-8"));
        System.out.println(resp);
        Map map = JSON.parseObject(resp, Map.class);
        String result = map.get("result") + "";
        Map map1 = JSON.parseObject(result, Map.class);
        String ret = map1.get("Status") + "";
        if(!"Success".equals(ret)){
            throw new LogicException("短信发送失败");
        }
    }
}
